#pragma once
#include <list>
#include <array>
#include <tuple>
#include <string>

struct Solid;
struct Face;
struct Loop;
struct HalfEdge;
struct Edge;
struct Vertex;

using U32 = unsigned int;
using I32 = int;

struct Coord
{
	float x, y, z;
};

struct Function
{
	float x, y, z, s;
};

struct Vertex
{
//	HalfEdge* halfEdge = nullptr;
	Coord coord;
};

struct Edge
{
	HalfEdge* halfEdge0 = nullptr;
	HalfEdge* halfEdge1 = nullptr;
};

struct HalfEdge
{

	Loop*	parentLoop = nullptr;
	Edge*	parentEdge = nullptr;
	Vertex*	vertex = nullptr;

	HalfEdge* next = nullptr;
	HalfEdge* pre = nullptr;

	HalfEdge* mate();
};

struct Loop
{
	Face*		parentFace = nullptr;
	HalfEdge*	leadingHalfEdge = nullptr;

	HalfEdge* find(Vertex* vertex);
};

struct Face
{
	Solid*				parentSolid = nullptr;
	Loop*				outerLoop = nullptr;
	std::list<Loop*>	innerLoops;
//	Function			function;
};

struct Solid
{
	std::list<Face*>	faces;
	std::list<Edge*>	edges;
	std::list<Vertex*>	vertices;
};

std::tuple<Vertex*, Face*, Solid*> MakeVertexFaceSolid(const Coord& coord);
// may change the leading halfedge of loop
std::tuple<Edge*, Vertex*> MakeEdgeVertex(Vertex* vertex0, Loop* loop, Coord coord);
std::tuple<Edge*, Face*> MakeEdgeFace(Loop* loop, Vertex* vertex0, Vertex* vertex1);
std::tuple<Loop*> KillEdgeMakeRing(Vertex* vertex0, Vertex* vertex1, Loop* loop0);
void KillFaceMakeRingHole(Loop* outerLoop, Loop* innerLoop);
void Sweep(Face* face, Coord dir);
void Print(Solid* solid, const std::string& path);